\chapter{Extra Assignments}
\label{extra-asgn}

% TODO this chapter needs to be cleaned up and organized a bit better, and parts are a bit too sarcastic for general publication

The features listed on this page are not extra credit. \textbf{There is no extra credit in Weenix.} Your grade is based on how well you complete the core Weenix requirements. Therefore trying to implement these things can only hurt your grade and distract you from what is really important in life. The only thing to be gained by foolishly ignoring this warning is a deeper understanding of Weenix and bragging rights. \textbf{We will look unfavorably on someone who has implemented some of these, but has problems with the core Weenix projects.}

Some items on this page include descriptions on when it is feasible to implement them, be aware however that you should always keep around a copy of your work which does not contain your work on extra features in case you break something. \textbf{Having a broken Weenix because you tried to implement one of these features is not acceptable.} This is particularly important to remember because you might implement a feature between \wlink{vfs}{VFS} and \wlink{s5fs}{S5FS} only to find later when working on \wlink{vm}{VM} that you broke something badly.

Also note that the course staff will only be able to provide limited help with these features. Some of the features have been implemented in the staff version of the code, others have been attempted and abandoned, still others are random whims which may or may not be impossible.

\section{Realistic projects}
If you ignored the warning above then this is the place to start. These are features which are known to be possible because someone has either done so or it has been planned. This means you will get some description here on how to implement it and there might even be helpful code already in Weenix.

\subsection{Multithreaded processes}
This task has a bunch of places in code that are marked by the \texttt{\_\_MTP\_\_} symbol (which must be enabled by setting ``\texttt{MTP = 1}'' in \texttt{Config.mk}), and the kernel is designed around it anyway. This is a relatively straightforward addition to the kernel.

\subsection{Current working directory}
This will add a system call which looks up the full path name of the current working directory of the current process and is marked in the codebase with the symbol \texttt{\_\_GETCWD\_\_}, which can be enabled by setting ``\texttt{GETCWD = 1}'' in \texttt{Config.mk}. This should not be too difficult at all.

\subsection{File system mounting}
One important missing feature in our VFS implementation is mount points. We have a root file system (\texttt{ramfs} if you are working on \wlink{vfs}{VFS}, \texttt{s5fs} if you are working on \wlink{s5fs}{S5FS}), but normal UNIX allows you to access multiple file systems by ``mounting'' additional file systems on directories in your virtual file system layer.

For more information on mount points we refer you to the \texttt{mount(2)} man pages, the \texttt{umount(2)} man pages, the lecture slides, and the text book.

Before you begin, there is already a significant amount of code in Weenix for this feature; however, by default it is not compiled. To compile this code change the line ``\texttt{MOUNTING = 0}'' in \texttt{Config.mk} to ``\texttt{MOUNTING = 1}''. Also, remember to run:
\begin{verbatim}
$ make clean\end{verbatim}

% TODO cscope
You should use \texttt{cscope} to search for all instances of the C symbol \texttt{\_\_MOUNTING\_\_} in Weenix to see exactly what has changed to allow mounting to happen. Notice that \texttt{struct fs} in \texttt{fs/vfs.h} now has a new field called \texttt{vn\_mount}.

The biggest change caused by changing the \texttt{MOUNTING} flag is the behavior of \texttt{vget()} (even though very little code changed, the behavior is completely different). The easiest way to think of the behavior of the new \texttt{vget()} is like this:
\begin{verbatim}
vnode_t* new_vget(args) {
    vnote_t* vn = old_vget(args);
    if (!error) {
        return vn->vn_mount;
    } else {
        return error;
    }
}\end{verbatim}

The purpose of this change is to make the integration of mounting as seamless as possible. Normally \texttt{vn->vn\_mount == vn} and therefore most of the time this new behavior is identical to the old one; however, simply by setting the \texttt{vn\_mount} field the \texttt{vget()} function automatically traverses into mounted file systems for us. The only cases we need to worry about are when we are leaving a mounted file system (e.g. following a \texttt{..} path from the root of a mounted file system).

The easier part of implementing mounting is filling in some functions which have been left blank (but fully commented!) for you. In \texttt{fs/vfs.c} this is:
\begin{verbatim}
int vfs_mount(struct vnode *mtpt, fs_t *fs);
int vfs_umount(fs_t *fs);\end{verbatim}
in \texttt{fs/vfs\_syscall.c} there is also:
\begin{verbatim}
int do_mount(const char *source, const char *target,
             const char *type);
int do_umount(const char *target);\end{verbatim}

You will also want to read the Hackers Guide section about reference counting for information about special conventions used when reference counting mount point \texttt{vnode\_t}s.

Now comes the hard part: implementing these functions is not enough. As was noted in the previous section, setting up the \texttt{vn\_mount} field will allow us to enter mounted file systems. However following \texttt{..} paths out of mounted file systems still needs to be special cased. You will need to think about the code you wrote for \wlink{vfs}{VFS} and which code will need to be different in order to handle mounting correctly. The amount of code you will need to write is small, but you need to find the right functions to write it. All of the code should go into functions which you wrote for \wlink{vfs}{VFS}. You do not need to modify functions which you wrote for other projects or functions which you did not write originally. Also remember some of the system calls have errors specific to mounting which you might not have worried about before (e.g. What happens when you try to link a file from one file system onto another? Why is this an error?).

\subsection{User preemption}
Definitely possible. People have done it for the old version of Weenix (running on the Brown Simulator) but due to the changes in how timer interrupts work between the old Brown Simulator and the new architectures it is not trivial to port their work over. The basic idea is that a timer interrupt is scheduled to occur every several milliseconds. The interrupt context then looks at the thread which was interrupted. If the thread was in user space it is safe to just put that thread on the run queue and switch into the context of another thread (thus preempting the user land process). If the interrupted thread was in kernel land we do not want to arbitrarily preempt it (preemptable kernels lead to kernel hacker hell). Instead, we set a flag on the thread to mark it as preempted and allow it to continue. When a thread returns from kernel land into user land the flag should get checked and if it is set the preemption should happen at that point. Make sure you understand all of this before you start or things will get messy.

So, do you gain anything from doing this? Actually, the effects are very visible and very satisfying. You will be able to run \texttt{vfstest} and \texttt{cat hamlet} at the same time and they will all look like they are running at the same time (assuming you set a good preemption time) while your fellow students will have very visible times when one operation stops working while the other is running. Also, your Weenix will not hang while you \texttt{cat /dev/zero} to \texttt{/dev/null}.

\subsection{Asynchronous disk driver}
It would be cool to support an asynchronous disk driver. To do this would require a decent amount of restructuring in the driver code, but is doable given a bit of time and effort. After this is done, you could potentially add asynchronous user I/O support as well (although this is a harder problem because in most Unix distributions the notification of a completion is done through signals).

\subsection{Better scheduling}
After you have finished implementing processes and threads, you should know the basics, but it might be a bad idea to try making too many big changes to Weenix before you have really gotten exposed to everything. % TODO processes and threads

The current Weenix scheduler is rather primitive as it has no sense of priorities and makes no attempt to do any ``clever'' scheduling, it is purely first come first serve. Here are some helpful suggestions:
\begin{itemize}
    \item Professor Doeppner's lecture (only available to Brown students) on scheduling contains plenty of information on different scheduling algorithms (you might also check the textbook).
    \item The CS167 students implement a slightly more advanced scheduler for their threading library assignment. You might be able to get some inspiration from that handout or the support code.
    \item If you decide to pursue user space preemption you might be able to tie it in nicely with a more advanced scheduler (e.g. threads which have been running for a long time and keep getting preempted should get a lower priority than threads which have just recently woken up after being asleep. As described in the lectures on scheduling, this can help because the long running programs tend to be background processes, while things which have just woken up are probably user processes which just received input). % TODO user space preemption
\end{itemize}

These haven't been implemented yet, although doing so theoretically wouldn't be too hard. The downside is that it will probably not have very visible effects, but you might be able to think of a good way to show off its effects that we have not.

\subsection{Block device special files}
Tricky and yet not so tricky. Talk to Robert Mustacchi about this if you're interested.

\section{``Abandon all hope, ye who enter here''}
If you ignored the Dante quote above then this is the place to start. These are the features that we know are either very difficult or completely impossible. However, we would hate to stop a truly foolish individual from banging their head against the keyboard until one of these features pops out.

\subsection{Signals}
Signals are cool, but they get pretty ugly pretty fast when you start doing stack manipulations in assembly. Not a serious suggestion currently as it would just severely complicate the codebase.
\subsection{Networking stack}
If you've taken a networking class where you implemented TCP/IP, you could try this one out. However, before you start, don't forget to write an Ethernet driver from scratch.
\subsection{Multi-core/processor support}
Two big problems with this, both of which are impossible to overcome.
\subsection{X window system}
Depends on signals, graphical display driver with higher resolution than $80x25$, mouse driver, etc.
\subsection{Users}
Bonus points for capability-based security.
\subsection{64-bit support}
This one is obviously trivial. It's amazing this hasn't been done yet.
\subsection{Kernel preemption}
Would require totally redesigning the Weenix kernel to make it threadsafe. If this seems reasonable, you are misunderstanding something. Userspace preemption is similar and doesn't require a full rewrite of Weenix. Also note that most production kernels don't even support this (because even after you get it working, it's an absolute nightmare to maintain, and it typically adds very little value). % TODO userspace preemption
 
